Building Docker Images for React Applications
Docker can also be used to containerize frontend applications like React. This process allows you to easily share, deploy, and run your React applications on any platform.
Let’s explore how to:
- Create a Dockerfile for a React app
- Build custom Docker images
- Run the image with or without Docker Compose
Example 1: Simple React Application
We will start by creating a basic React application using create-react-app
, and then containerize it using Docker.
Step 1: Initialize a React App
If you haven't already, create a React app by running the following command:
npx create-react-app my-react-app
This creates a React app in the my-react-app
directory.
Step 2: Writing the Dockerfile
Create a Dockerfile
inside the my-react-app
directory.
# Use an official Node runtime as a parent image
FROM node:20-alpine
# Set the working directory inside the container
WORKDIR /app
# Copy the package.json and package-lock.json to the container
COPY package*.json ./
# Install the dependencies
RUN npm install
# Copy the rest of the React app source code into the container
COPY . .
# Build the app for production
RUN npm run build
# Use Nginx to serve the built React app
FROM nginx:alpine
COPY --from=0 /app/build /usr/share/nginx/html
# Expose port 80
EXPOSE 80
# Start Nginx server
CMD ["nginx", "-g", "daemon off;"]
Explanation:
FROM node:16-alpine
: Use a lightweight Node.js image based on Alpine Linux for building the app.WORKDIR /app
: Set/app
as the working directory inside the container.COPY package*.json ./
: Copypackage.json
andpackage-lock.json
to install dependencies first.RUN npm install
: Install the app dependencies (React and other libraries).COPY . .
: Copy the remaining app files into the/app
directory.RUN npm run build
: Build the React app for production.FROM nginx:alpine
: Switch to a minimal Nginx image to serve the built app. This results in a smaller final image.COPY --from=0 /app/build /usr/share/nginx/html
: Copy thebuild
folder (the output ofnpm run build
) from the first stage into the Nginx web server’shtml
directory.EXPOSE 80
: Expose port 80 for HTTP traffic.CMD ["nginx", "-g", "daemon off;"]
: Run Nginx to serve the app.
Two Ways to Run Your React Docker Image
You can run your Docker image using either Docker Compose or directly using Docker commands.
1. Running with Docker Compose
Here’s a docker-compose.yml
file for running the React app using Docker Compose:
version: '3'
services:
react-app:
build: .
ports:
- "3000:80"
volumes:
- .:/app
stdin_open: true
tty: true
Explanation:
build: .
: Tells Docker Compose to build the image from the current directory where the Dockerfile resides.ports: "3000:80"
: Maps port3000
on the host to port80
in the container (Nginx).volumes: .:/app
: Mounts the current directory into the container so you can make live changes to the code.stdin_open
andtty
: These flags allow you to attach a terminal to the container if needed.
Run the app using Docker Compose with:
docker compose up
This command will:
- Build the Docker image.
- Start the container.
- Map port
3000
on your machine to port80
in the container.
Access the React app at http://localhost:3000
.
2. Running Without Docker Compose
You can also run the app directly using Docker commands.
First, build the Docker image:
docker build -t my-react-app .
Then, run the container:
docker run -p 3000:80 my-react-app
This command maps port 3000
on your machine to port 80
in the container, allowing you to access the React app at http://localhost:3000
.
Example 2: Optimizing the React Build for Production
React apps often need optimization when built for production. Docker’s multi-stage builds can help create lightweight images, ensuring the app is fast and efficient.
Here’s how we can optimize the Dockerfile:
# Stage 1: Build the React app
FROM node:16-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Stage 2: Serve the built app using Nginx
FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Explanation:
FROM node:16-alpine AS builder
: Use a multi-stage build where the first stage (builder
) is responsible for building the app.COPY --from=builder
: In the second stage, copy only the built files from thebuilder
stage to the Nginx image, reducing the final image size.
Example 3: Using Environment Variables in Docker for React
You can pass environment variables to a React app at build time. Here's how:
- In the React app, create a
.env
file to store environment variables:
REACT_APP_API_URL=https://api.example.com
- Update the Dockerfile to copy this
.env
file:
# Stage 1: Build the React app
FROM node:16-alpine AS builder
WORKDIR /app
COPY package*.json ./
COPY .env /app/.env # Add this line
RUN npm install
COPY . .
RUN npm run build
# Stage 2: Serve the built app using Nginx
FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
This is especially useful because in most cases you will be having a seperate backend for your react application and it is better to pass the backend url as an environment variable than hardcode it.
Summary
- Dockerfiles for React apps follow a similar pattern to backend apps, but they include
npm
commands for building the app and a web server like Nginx for serving the static build files. - You can run the Dockerized React app with or without Docker Compose.
This section now covers React applications with examples of multi-stage builds and environment variables, giving both Compose and non-Compose methods to run the app.